<?php
/**
 * Created by PhpStorm.
 * User: jaylen
 * Date: 2020-06-02
 * Time: 15:28
 */

namespace app\common\service;


use app\common\enum\ScopeEnum;
use app\common\exception\ForbiddenException;
use app\common\exception\TokenException;
use think\facade\Cache;
use think\facade\Config;
use think\facade\Request;

class Token
{
    /**
     * 生成Token字符串
     * @return string
     */
    public static function generateToken()
    {
        //生成32位长度的随机字符串
        $randChars = get_rand_char(32);
        //获取访问时间戳
        $timeStamp = $_SERVER['REQUEST_TIME'];
        //salt盐
        $salt = Config::get('secure.token_salt');

        //进行MD5加密
        return md5($randChars.$timeStamp.$salt);
    }

    /**
     * 验证Token是否存在
     * @param $token
     * @return bool
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function verifyToken($token)
    {
        if (Cache::store('redis')->get($token) !== false) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取当前Token对应的uid
     * @return mixed
     * @throws TokenException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function getCurrentUID()
    {
        return self::getCurrentTokenVar('uid');
    }

    //权限检查操作
    /**
     * 检查权限是否比普通用户高
     * @return bool
     * @throws ForbiddenException
     * @throws TokenException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function needPrimaryScope()
    {
        $scope = self::getCurrentTokenVar('scope');
        if ($scope){
            if ($scope > ScopeEnum::USER){
                return true;
            }else{
                throw new ForbiddenException();
            }
        }else{
            throw new TokenException();
        }
    }

    /**
     * 检查权限是否为普通用户
     * @return bool
     * @throws ForbiddenException
     * @throws TokenException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function needExclusiveScope()
    {
        $scope = self::getCurrentTokenVar('scope');
        if ($scope){
            if ($scope == ScopeEnum::USER){
                return true;
            }else{
                throw new ForbiddenException();
            }
        }else{
            throw new TokenException();
        }
    }

    /**
     * 检查权限是否为游客用户
     * @return bool
     * @throws ForbiddenException
     * @throws TokenException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function needGuestScope()
    {
        $scope = self::getCurrentTokenVar('scope');
        if ($scope){
            if ($scope == ScopeEnum::GUEST){
                return true;
            }else{
                throw new ForbiddenException();
            }
        }else{
            throw new TokenException();
        }
    }

    /**
     * 获取当前Token对应的键的值
     * @param $key
     * @return mixed
     * @throws TokenException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function getCurrentTokenVar($key)
    {
        //接收通过头部传递的Token
        $token = Request::instance()
            ->header('token');

        // 从缓存中取出对应token所存在用户的相关信息
        $vars = Cache::store('redis')->get($token);
        if (empty($vars)) {
            throw new TokenException();
        } else {
            if (!is_array($vars)) {
                $vars = json_decode($vars,true);
            }

            //判断是否有对应的键值，如果没有记录到日志并抛出异常
            if (array_key_exists($key,$vars)) {
                return $vars[$key];
            } else {
                throw new \Exception('尝试获取的 '.$key.' Token变量不存在');
            }
        }
    }

    /**
     * 通过Token判断用户是否为普通用户（不进行权限异常处理）
     * @return bool
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public static function checkUserPermission()
    {
        //接收通过头部传递的Token
        $token = Request::instance()
            ->header('token');

        // 从缓存中取出对应token所存在用户的相关信息
        $vars = Cache::store('redis')->get($token);
        if (empty($vars)) {
            return false;
        } else {
            if (!is_array($vars)) {
                $vars = json_decode($vars,true);
            }

            // 取出scope的值
            if (array_key_exists('scope',$vars)) {
                if (!empty($vars['scope'])) {
                    if ($vars['scope'] >= ScopeEnum::USER) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }
}